package com.inspur.edp.common.expr.visitor;

import com.inspur.edp.common.expr.ast.ASTContext;
import com.inspur.edp.common.expr.ast.CompileUnitParser;
import com.inspur.edp.common.expr.ast.CompileUnitVisitor;
import com.inspur.edp.common.expr.constant.ExpressResourceKey;
import com.inspur.edp.common.expr.exception.ExpressBizException;
import com.inspur.edp.common.expr.exception.ExpressException;
import com.inspur.edp.common.expr.parser.*;
import com.inspur.edp.common.expr.visitor.array.ArrayAccessManager;
import com.inspur.edp.common.expr.visitor.construct.JavaConstructManager;
import com.inspur.edp.common.expr.visitor.field.FieldAccessManager;
import com.inspur.edp.common.expr.visitor.field.FieldDeserializeFactory;
import com.inspur.edp.common.expr.visitor.nullvalue.NullValueFactory;
import com.inspur.edp.common.expr.visitor.nullvalue.NullValueVisitor;
import com.inspur.edp.common.expr.visitor.parameter.ParameterVisitManager;
import com.inspur.edp.common.expr.visitor.type.PrimitiveTypeVisitor;
import com.inspur.edp.common.expr.visitor.type.TypeDecoratorVisitor;
import com.inspur.edp.common.type.*;
import com.inspur.edp.common.type.cache.TypeThreadCache;
import com.inspur.edp.common.type.constant.TypeConstant;
import com.inspur.edp.common.type.parser.TypeCompareMgr;
import com.inspur.edp.common.type.parser.TypeParser;
import com.inspur.edp.common.type.utils.TypeUtil;
import io.iec.edp.caf.commons.utils.StringUtils;
import lombok.Data;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.RuleNode;
import org.antlr.v4.runtime.tree.TerminalNode;

import java.util.*;

/**
 * @author lizhaorui
 * @date 2025/8/18
 * @description
 */
@Data
public class JavaVisitor implements CompileUnitVisitor, ASTContext {

    private String dsl;

    private int globalVarIndex;

    // 代码格式
    private int tabKeyCount;

    //import map key：className value: typeFullName
    private Map<String, String> dslImportMap;

    private Map<String, String> javaImportMap;

    //本地内部类型
    private List<String> localTypes;

    private Map<ParserRuleContext, List<String>> context_statement_map;

    //key 变量名称 value 类型
    private List<VariableData> varName_type_list;

    // context栈，用于获取当前context
    private Stack<ParserRuleContext> varStack;

    // context栈，用于获取当前context
    private Stack<ParserRuleContext> blockStack;

    private Type thisDSLClass;

    private String mainClassName;

    private List<CompileUnitParser.MethodDeclarationContext> extraMethods;

    public JavaVisitor() {
        this.tabKeyCount = 0;
        this.varName_type_list = new ArrayList<VariableData>();
        this.varStack = new Stack<>();
        this.blockStack = new Stack<>();
        this.dslImportMap = new HashMap<>();
        this.localTypes = new ArrayList<>();
        this.javaImportMap = new HashMap<>();
        this.context_statement_map = new HashMap<>();
        this.extraMethods = new ArrayList<>();
    }

    @Data
    public static class VariableData {

        private Map<String, TypeRefer> map;

        private boolean isolate;

        public VariableData(boolean isolate) {
            this.isolate = isolate;
            this.map = new HashMap<>();
        }

        public boolean contains(String varName) {
            return this.map.containsKey(varName);
        }

        public void addVar(String varName, TypeRefer typeRefer) {
            this.map.put(varName, typeRefer);
        }

        public TypeRefer get(String varName) {
            return this.map.get(varName);
        }
    }

    public String generateJava(String dsl) {
        this.dsl = dsl;
        CompileUnitParser compileUnitParser = ASTParser.parse(dsl);
        CompileUnitParser.CompileUnitContext ctx = compileUnitParser.compileUnit();
        //设置this type
        DSLTypeBuilder dslBuilder = new DSLTypeBuilder();
        String url = "this";
        Type thisType = dslBuilder.build(url, ctx).get(0);
        thisType.setSource("temp");
        thisType.setTypeId(thisType.getTypeOptCode());
        this.setThisDSLClass(thisType);
        TypeThreadCache.add(thisType);
        String typeCode = this.visitCompileUnit(ctx).toString();
        StringBuilder sb = new StringBuilder();
        for (Map.Entry entry : this.javaImportMap.entrySet()) {
            String importStr = (String) entry.getValue();
            if (importStr.indexOf(".") > 0) {
                sb.append("\nimport " + entry.getValue() + ";");
            }
        }
        sb.append("\n");
        sb.append(typeCode);
        return sb.toString();
    }

    private void addJavaImport(String importStr) {
        if (!this.javaImportMap.containsKey(importStr)) {
            this.javaImportMap.put(importStr, importStr);
        }
    }

    private void addJavaImports(List<String> imports) {
        if (imports != null) {
            for (String importStr : imports) {
                this.addJavaImport(importStr);
            }
        }
    }

    private List<String> genericTypeNames;

    @Override
    public List<String> getGenericTypeNames() {
        if (this.genericTypeNames == null) {
            this.genericTypeNames = new ArrayList<>();
        }
        return genericTypeNames;
    }

    private ParserRuleContext getVarContext() {
        if (varStack.empty()) {
            throw new ExpressException("当前没有上下文。");
        }
        return varStack.peek();
    }

    private ParserRuleContext getBlockContext() {
        if (blockStack.empty()) {
            throw new ExpressException("当前没有上下文。");
        }
        return blockStack.peek();
    }

    private void putContextVar(ParserRuleContext context, String varName, TypeRefer typeRefer) {
        this.addVariable(varName, typeRefer);
    }

    private void removeContextVar() {
        this.varName_type_list.remove(this.varName_type_list.size() - 1);
    }

    public String getNextGlobalVarName(String typeName) {

        char first = typeName.charAt(0);
        if (first >= 'A' && first <= 'Z') {
            typeName = typeName.substring(0, 1).toLowerCase() + typeName.substring(1);
        }
        return typeName + "_var_" + (globalVarIndex++);
    }

    public void addDSLTypeImports(List<String> typeFullNames) {
        if (typeFullNames == null) {
            return;
        }
        for (String typeFullName : typeFullNames) {
            String className = TypeUtil.getTypeCode(typeFullName);
            this.dslImportMap.put(className, typeFullName);
        }
    }

    public void addJavaTypeImport(String typeFullName) {
        this.javaImportMap.put(typeFullName, typeFullName);
    }

    public void addJavaTypeImports(List<String> typeFullNames) {
        if (typeFullNames == null || typeFullNames.size() == 0) {
            return;
        }
        for (String typeFullName : typeFullNames) {
            this.addJavaTypeImport(typeFullName);
        }
    }


    public void appendTabKey(StringBuilder sb) {
        for (int i = 0; i < tabKeyCount; i++) {
            sb.append("\t");
        }
    }

    public void appendWsAndStr(StringBuilder sb, String word) {
        sb.append(" " + word);
    }


    @Override
    public Object visitProgram(CompileUnitParser.ProgramContext ctx) {
        return "";
    }

    @Override
    public Object visitCompileUnit(CompileUnitParser.CompileUnitContext ctx) {
        StringBuilder sb = new StringBuilder();
        List<CompileUnitParser.ImportInfoContext> imports = ctx.importInfo();
        if (imports != null && imports.size() > 0) {
            for (CompileUnitParser.ImportInfoContext tmpImport : imports) {
                sb.append(this.visitImportInfo(tmpImport).toString());
            }
        }
        List<CompileUnitParser.CompileUnitTypesContext> typesContexts = ctx.compileUnitTypes();
        if (typesContexts != null && typesContexts.size() > 0) {
            for (CompileUnitParser.CompileUnitTypesContext type : typesContexts) {
                sb.append(this.visitCompileUnitTypes(type).toString());
            }
        }
        return sb.toString();
    }

    @Override
    public Object visitCompileUnitTypes(CompileUnitParser.CompileUnitTypesContext ctx) {
        if (ctx == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        sb.append(this.visitTypeDeclaration(ctx.typeDeclaration()).toString());
        sb.append(this.visitFunctionDeclaration(ctx.functionDeclaration()).toString());
        return sb.toString();
    }

    @Override
    public Object visitImportInfo(CompileUnitParser.ImportInfoContext ctx) {
        StringBuilder sb = new StringBuilder();
        String from = ctx.StringLiteral().getText();
        for (TerminalNode simpleName : ctx.SimpleName()) {
            String typeSimpleName = simpleName.getText();
            from = from.substring(1, from.length() - 1);
            this.dslImportMap.put(typeSimpleName, from);
            //添加 java import
            String javaPackageName = TypeThreadCache.getByUrl(from).getTypeOptCode();
            if (javaPackageName.indexOf(".") > 0) {
                this.addJavaTypeImport(javaPackageName);
            }
        }
        return "";
    }

    @Override
    public Object visitModifierKeyword(CompileUnitParser.ModifierKeywordContext ctx) {
        if (ctx == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        sb.append(this.visitTerminal(ctx.Private()).toString());
        sb.append(this.visitTerminal(ctx.Public()).toString());
        sb.append(this.visitTerminal(ctx.Protected()).toString());
        return sb.toString();
    }

    @Override
    public Object visitName(CompileUnitParser.NameContext ctx) {
        if (ctx == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        sb.append(this.visitName(ctx.name()).toString());
        sb.append(this.visitTerminal(ctx.Dot()).toString());
        sb.append(this.visitTerminal(ctx.SimpleName()).toString());
        return sb.toString();
    }

    @Override
    public Object visitTypeDeclaration(CompileUnitParser.TypeDeclarationContext ctx) {
        if (ctx == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        this.appendTabKey(sb);

        //类型标签
        sb.append(TypeDecoratorVisitor.visit(this, ctx));

        sb.append("public");
        sb.append(" ");
        if (ctx.Class() != null) {
            sb.append("class");
        } else if (ctx.Enum() != null) {
            sb.append("enum");
        } else {
            throw new ExpressException("type only support class and enum.");
        }
        //类名
        sb.append(" ");
        String className = this.visitTerminal(ctx.SimpleName()).toString();
        this.mainClassName = className;
        sb.append(className);
        sb.append(this.visitGenericTypeDeclaration(ctx.genericTypeDeclaration()).toString());
        sb.append(this.visitExtendDeclaration(ctx.extendDeclaration()).toString());
        sb.append(this.visitImplementsDeclaration(ctx.implementsDeclaration()).toString());
        //类内容开始
        this.appendWsAndStr(sb, "{");
        sb.append(this.visitBodyDeclarations(ctx.bodyDeclarations()).toString());

        //扩展方法
        if (this.extraMethods.size() > 0) {
            tabKeyCount++;
            for (CompileUnitParser.MethodDeclarationContext tmpMethod : this.extraMethods) {
                sb.append(this.visitMethodDeclaration(tmpMethod));
            }
            tabKeyCount--;
        }

        //类内容结束
        sb.append("\n}");
        return sb.toString();
    }

    @Override
    public Object visitGenericTypeDeclaration(CompileUnitParser.GenericTypeDeclarationContext ctx) {
        return "";
    }

    @Override
    public Object visitGenericType(CompileUnitParser.GenericTypeContext ctx) {
        if (ctx == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        List<CompileUnitParser.TypeContext> types = ctx.type();
        sb.append(TypeVisitor.visit(types.get(0), this));
        if (types.size() > 1) {
            sb.append(this.visitTerminal(ctx.LessThan()));
            for (int index = 1; index < types.size(); index++) {
                if (index > 1) {
                    sb.append(",");
                }
                sb.append(TypeVisitor.visit(types.get(index), this));
            }
            sb.append(this.visitTerminal(ctx.GreaterThan()).toString());
        }
        return sb.toString();
    }

    @Override
    public Object visitPrimitiveType(CompileUnitParser.PrimitiveTypeContext ctx) {
        if (ctx == null) {
            return "";
        }
        CompileUnitParser.PrimitiveTypeEnumContext context = ctx.primitiveTypeEnum();
        return PrimitiveTypeVisitor.visit(context, this);
    }


    @Override
    public Object visitStringType(CompileUnitParser.StringTypeContext ctx) {
        if (ctx == null) {
            return "";
        }
        return "String";
    }


    @Override
    public Object visitBooleanType(CompileUnitParser.BooleanTypeContext ctx) {
        if (ctx == null) {
            return "";
        }
        return this.visitTerminal(ctx.Boolean());
    }

    @Override
    public Object visitIntType(CompileUnitParser.IntTypeContext ctx) {
        if (ctx == null) {
            return "";
        }
        return "int";
    }

    @Override
    public Object visitFloatType(CompileUnitParser.FloatTypeContext ctx) {
        if (ctx == null) {
            return "";
        }
        return "float";
    }

    @Override
    public Object visitDoubleType(CompileUnitParser.DoubleTypeContext ctx) {
        if (ctx == null) {
            return "";
        }
        return "double";
    }

    @Override
    public Object visitLongType(CompileUnitParser.LongTypeContext ctx) {
        if (ctx == null) {
            return "";
        }
        return "long";
    }

    @Override
    public Object visitAnyType(CompileUnitParser.AnyTypeContext ctx) {
        if (ctx == null) {
            return "";
        }
        return this.visitTerminal(ctx.Any());
    }

    @Override
    public Object visitExtendDeclaration(CompileUnitParser.ExtendDeclarationContext ctx) {
        if (ctx == null) {
            return "";
        }
        return " " +
                this.visitTerminal(ctx.Extends()) +
                " " +
                TypeVisitor.visit(ctx.type(), this);
    }

    @Override
    public Object visitImplementsDeclaration(CompileUnitParser.ImplementsDeclarationContext ctx) {
        if (ctx == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        sb.append(" ");
        sb.append(this.visitTerminal(ctx.Implements()).toString());
        sb.append(" ");
        List<CompileUnitParser.TypeContext> types = ctx.type();
        if (types != null && types.size() > 0) {
            int index = 0;
            for (CompileUnitParser.TypeContext type : types) {
                if (index > 0) {
                    sb.append(",");
                }
                sb.append(TypeVisitor.visit(type, this));
                index++;
            }
        }
        return sb.toString();
    }

    @Override
    public Object visitBodyDeclarations(CompileUnitParser.BodyDeclarationsContext ctx) {
        if (ctx == null) {
            return "";
        }
        this.varStack.push(ctx);
        this.varName_type_list.add(new VariableData(true));

        StringBuilder sb = new StringBuilder();
        //1、字段处理
        List<CompileUnitParser.FieldDeclarationContext> fields = ctx.fieldDeclaration();
        if (fields != null && fields.size() > 0) {
            for (CompileUnitParser.FieldDeclarationContext field : fields) {
                tabKeyCount++;
                sb.append(this.visitFieldDeclaration(field));
                tabKeyCount--;
            }
        }
        //2、方法处理
        List<CompileUnitParser.MethodDeclarationContext> methodsContext = ctx.methodDeclaration();
        if (methodsContext != null && methodsContext.size() > 0) {
            tabKeyCount++;
            for (CompileUnitParser.MethodDeclarationContext tmpMethod : methodsContext) {
                sb.append(this.visitMethodDeclaration(tmpMethod));
            }
            tabKeyCount--;
        }

        this.removeContextVar();
        this.varStack.pop();

        return sb.toString();
    }

    @Override
    public Object visitFieldDeclaration(CompileUnitParser.FieldDeclarationContext ctx) {
        if (ctx == null) {
            return "";
        }

        StringBuilder sb = new StringBuilder();

        //序列化方法处理
        this.appendJsonSerializer(sb, ctx);

        //list序列化方法处理
        this.appendListSerializer(sb, ctx);

        sb.append("\n");
        this.appendTabKey(sb);
        //检查是否打了反序列化标签
        sb.append(this.visitModifierKeyword(ctx.modifierKeyword()));
        sb.append(" ");
        sb.append(this.visitTerminal(ctx.Static()));
        sb.append(" ");

        String fieldCode = this.visitTerminal(ctx.SimpleName()).toString();
        TypeRefer typeRefer = TypeAstParser.getTypeRefer(ctx.type(), this);
        this.addVariable(fieldCode, typeRefer);

        String typeJava = TypeVisitor.visit(ctx.type(), this);
        sb.append(typeJava);
        sb.append(" ");
        sb.append(fieldCode);
        String fieldValue = this.visitExpress(ctx.express()).toString();
        if (!fieldValue.equals("null")) {
            sb.append(" = ");
            sb.append(fieldValue);
        }
        sb.append(";");
        return sb.toString();
    }

    private void appendListSerializer(StringBuilder sb, CompileUnitParser.FieldDeclarationContext ctx) {
        TypeRefer dslType = TypeAstParser.getTypeRefer(ctx.type(), this);
        if (dslType.isList()) {
            if (dslType.getGenericTypes() != null || dslType.getGenericTypes().size() > 0) {
                //处理import
                this.addJavaImport("com.fasterxml.jackson.databind.annotation.JsonDeserialize");
                this.addJavaImport("com.inspur.edp.rule.dsl.common.api.deserialize.GenericType");
                this.addJavaImport("com.inspur.edp.rule.dsl.common.api.deserialize.ListDeserializer");
                this.appendTabKey(sb);
                sb.append("\n@JsonDeserialize(using = ListDeserializer.class)");
                TypeRefer genericType = dslType.getGenericTypes().get(0);
                String javaGenericType = TypeVisitor.visit(genericType, this);
                this.appendTabKey(sb);
                sb.append("\n@GenericType(type = " + javaGenericType + ".class)");
            }
        }
    }

    private void appendJsonSerializer(StringBuilder sb, CompileUnitParser.FieldDeclarationContext ctx) {
        Map<String, DecorationOption> decoratorMap = DecoratorParser.getDecoratorMap(ctx.decorator());
        DecorationOption decorationOption = decoratorMap.get(Field.JSON_DESERIALIZER_NAME);
        if (decorationOption != null) {
            String kind = decorationOption.getValue(TypeConstant.KIND);
            String javaAnnotation = FieldDeserializeFactory.getSpi(kind).getJavaAnnotation();
            sb.append("\n");
            this.appendTabKey(sb);
            sb.append(javaAnnotation);
        }
    }

    @Override
    public Object visitConstructorDeclaration(CompileUnitParser.ConstructorDeclarationContext ctx) {
        return "";
    }

    @Override
    public Object visitMethodDeclaration(CompileUnitParser.MethodDeclarationContext ctx) {
        if (ctx == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        //方法注解生成
        sb.append(this.visitMethodAnnotation(ctx.parameterDeclarations()));
        sb.append("\n");
        this.appendTabKey(sb);
        sb.append("public");
        sb.append(" ");

        sb.append(this.visitTerminal(ctx.Static()));
        sb.append(" ");

        //返回类型
        sb.append(TypeVisitor.visit(ctx.type(), this));
        //方法名
        sb.append(" ");
        sb.append(this.visitTerminal(ctx.SimpleName()));
        sb.append("(");
        //初始化变量栈
        this.varStack.push(ctx);
        this.varName_type_list.add(new VariableData(true));
        sb.append(this.visitParameterDeclarations(ctx.parameterDeclarations()));
        sb.append(")");
        //方法体
        sb.append(this.visitBlock(ctx.block()));
        //释放变量栈
        this.removeContextVar();
        this.varStack.pop();
        return sb.toString();
    }

    public String visitMethodAnnotation(CompileUnitParser.ParameterDeclarationsContext ctx) {
        if (ctx == null) {
            return "";
        }
        List<String> listTags = new ArrayList<>();
        List<Integer> indexes = new ArrayList<>();
        List<String> classes = new ArrayList<>();
        List<String> typeIds = new ArrayList<>();
        List<CompileUnitParser.ParameterDeclarationContext> parameters = ctx.parameterDeclaration();
        if (parameters != null && parameters.size() > 0) {
            int index = 0;
            for (CompileUnitParser.ParameterDeclarationContext parameter : parameters) {
                Map<String, DecorationOption> decoratorMap = DecoratorParser.getDecoratorMap(parameter.decorator());
                DecorationOption listDecoration = decoratorMap.get(Parameter.LIST_NAME);
                TypeRefer dslType = TypeAstParser.getTypeRefer(parameter.type(), this);
                if (listDecoration != null) {
                    TypeRefer genericType = dslType.getGenericTypes().get(0);
                    String javaGenericType = TypeVisitor.visit(genericType, this);
                    indexes.add(index);
                    classes.add(javaGenericType);
                    typeIds.add(genericType.getTypeId());
                    listTags.add("true");
                } else {
                    if (dslType.getSource().equals(TypeConstant.BE_ENTITY_DATA)) {
                        String javaType = TypeVisitor.visit(dslType, this);
                        indexes.add(index);
                        classes.add(javaType);
                        typeIds.add(dslType.getTypeId());
                        listTags.add("false");
                    }
                }
                index++;
            }
        }
        if (indexes.size() == 0) {
            return "";
        } else {
            this.addJavaImport("com.inspur.edp.rule.dsl.common.api.deserialize.MethodParamAnnotation");
            StringBuilder sb = new StringBuilder();
            sb.append("\n");
            this.appendTabKey(sb);
            StringBuilder listTagStr = new StringBuilder();
            StringBuilder classStr = new StringBuilder();
            StringBuilder indexStr = new StringBuilder();
            StringBuilder typeIdStr = new StringBuilder();
            int count = 0;
            for (int i = 0; i < indexes.size(); i++) {
                if (count == 0) {
                    listTagStr.append(listTags.get(i));
                    classStr.append(classes.get(i)).append(".class");
                    indexStr.append(indexes.get(i));
                    typeIdStr.append("\"").append(typeIds.get(i)).append("\"");
                } else {
                    listTagStr.append(",").append(listTags.get(i));
                    classStr.append(",").append(classes.get(i)).append(".class");
                    indexStr.append(",").append(indexes.get(i));
                    typeIdStr.append(",").append("\"").append(typeIds.get(i)).append("\"");
                }
                count++;
            }
            sb.append(String.format("@MethodParamAnnotation(listTags = {%s} , types = {%s}, indexes = {%s}, typeIds = {%s})", listTagStr.toString(), classStr.toString(), indexStr.toString(), typeIdStr.toString()));
            return sb.toString();
        }
    }


    @Override
    public Object visitParameterDeclarations(CompileUnitParser.ParameterDeclarationsContext ctx) {
        if (ctx == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        List<CompileUnitParser.ParameterDeclarationContext> parameters = ctx.parameterDeclaration();
        if (parameters != null && parameters.size() > 0) {
            int i = 0;
            for (CompileUnitParser.ParameterDeclarationContext parameter : parameters) {
                if (i > 0) {
                    sb.append(", ");
                }
                sb.append(this.visitParameterDeclaration(parameter));
                i++;
            }
        }
        return sb.toString();
    }

    @Override
    public Object visitParameterDeclaration(CompileUnitParser.ParameterDeclarationContext ctx) {
        if (ctx == null) {
            return "";
        }
        //变量处理
        TypeRefer typeRefer = TypeAstParser.getTypeRefer(ctx.type(), this);
        this.putContextVar(this.getVarContext(), ctx.SimpleName().getText(), typeRefer);
        return TypeVisitor.visit(typeRefer, this) +
                " " +
                this.visitTerminal(ctx.SimpleName());
    }

    @Override
    public Object visitEnumValues(CompileUnitParser.EnumValuesContext ctx) {
        return "";
    }

    @Override
    public Object visitEnumValue(CompileUnitParser.EnumValueContext ctx) {
        return "";
    }

    @Override
    public Object visitDecorator(CompileUnitParser.DecoratorContext ctx) {
        return "";
    }

    @Override
    public Object visitDecoratorItem(CompileUnitParser.DecoratorItemContext ctx) {
        return "";
    }

    @Override
    public Object visitReferType(CompileUnitParser.ReferTypeContext ctx) {
        if (ctx == null) {
            return "";
        }
        return this.visitName(ctx.name());
    }


    @Override
    public Object visitArrayType(CompileUnitParser.ArrayTypeContext ctx) {
        if (ctx == null) {
            return "";
        }
        return " " +
                this.visitTerminal(ctx.OpenBracket()) +
                this.visitTerminal(ctx.CloseBracket());
    }


    @Override
    public Object visitVoidType(CompileUnitParser.VoidTypeContext ctx) {
        if (ctx == null) {
            return "";
        }
        return this.visitTerminal(ctx.Void());
    }

    @Override
    public Object visitThisExpr(CompileUnitParser.ThisExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        return this.visitTerminal(ctx.This());
    }

    @Override
    public Object visitObjectValueExpr(CompileUnitParser.ObjectValueExprContext ctx) {
        //如需实现，参见历史版本
        TypeRefer typeRefer = ctx.requireType;
        VisitResult visitResult = JavaConstructManager.visit(this, typeRefer, "");
        return this.handleVisitResult(visitResult);
    }

    @Override
    public Object visitArrayValueExpr(CompileUnitParser.ArrayValueExprContext ctx) {
        //如需实现，参见历史版本
        return "null";
    }

    @Override
    public Object visitPlusMinusPostExpr(CompileUnitParser.PlusMinusPostExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        return String.valueOf(this.visitExpress(ctx.express())) +
                this.visitTerminal(ctx.PlusPlus()) +
                this.visitTerminal(ctx.MinusMinus());
    }

    @Override
    public Object visitFieldAccessExpr(CompileUnitParser.FieldAccessExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        CompileUnitParser.ExpressContext objectExpr = ctx.express();
        String fieldCode = ctx.SimpleName().getText();
        boolean isGetter = true;
        if (ctx.parent instanceof CompileUnitParser.AssignValExprContext) {
            CompileUnitParser.AssignValExprContext parent = (CompileUnitParser.AssignValExprContext) ctx.parent;
            if (parent.express(0) == ctx) {
                isGetter = false;
            }
        }
        if (isGetter) {
            VisitResult javaVisitResult = FieldAccessManager.visitGetter(this, ctx, objectExpr, fieldCode);
            this.addJavaImports(javaVisitResult.getImports());
            return javaVisitResult.getScript();
        } else {
            return "";
        }
    }


    @Override
    public Object visitTypeCastExpr(CompileUnitParser.TypeCastExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        return "(" +
                TypeVisitor.visit(ctx.type(), this) +
                ")" +
                this.visitExpress(ctx.express());
    }

    @Override
    public Object visitArrayAccessExpr(CompileUnitParser.ArrayAccessExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        VisitResult visitResult = ArrayAccessManager.visitGetter(this, ctx.express(0), ctx.express(1));
        return visitResult.getScript();
    }

    @Override
    public Object visitUnaryMinusExpr(CompileUnitParser.UnaryMinusExprContext ctx) {
        return "-" + ctx.NumberLiteral().getText();
    }

    @Override
    public Object visitNewExpr(CompileUnitParser.NewExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        CompileUnitParser.BodyDeclarationsContext bodyDeclarationsContext = ctx.bodyDeclarations();
        if (bodyDeclarationsContext == null) {
            String parameters = this.visitParameters(ctx.parameters()).toString();
            VisitResult visitResult = JavaConstructManager.visit(this, ctx.type(), parameters);
            return this.handleVisitResult(visitResult);
        } else {
            //匿名函数
            StringBuilder sb = new StringBuilder();
            sb.append(" new ");
            String typeStr = TypeVisitor.visit(ctx.type(), this);
            sb.append(typeStr + "(){");
            sb.append(this.visitBodyDeclarations(bodyDeclarationsContext));
            sb.append("\n");
            this.appendTabKey(sb);
            sb.append("}");
            return sb.toString();
        }
    }

    public String handleVisitResult(VisitResult visitResult) {
        this.addJavaImports(visitResult.getImports());
        return visitResult.getScript();
    }


    @Override
    public Object visitNumberValExpr(CompileUnitParser.NumberValExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        String numberString = this.visitTerminal(ctx.NumberLiteral()).toString();
        if (ctx.requireType != null && ctx.requireType.isBigDecimal()) {
            this.addJavaTypeImport("java.math.BigDecimal");
            return String.format("new BigDecimal(%s)", numberString);
        }
        return numberString;
    }


    @Override
    public Object visitMethodInvokeExpr(CompileUnitParser.MethodInvokeExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        CompileUnitParser.ExpressContext objectExpr = ctx.express();
        ExpressVisitManager.ExpressVisitor expressVisitor = ExpressVisitManager.getVisitor(objectExpr);
        //校验方法是否存在
        TypeRefer objectTypeRefer = ExpressAstParser.getOriginalType(objectExpr, this);
        String objectExprStr = expressVisitor.visit(objectExpr, this).toString();
        return objectExprStr +
                this.visitTerminal(ctx.Dot()).toString() +
                this.visitTerminal(ctx.SimpleName()) +
                this.visitTerminal(ctx.OpenParen()) +
                this.visitParameters(ctx.parameters()) +
                this.visitTerminal(ctx.CloseParen());
    }

    @Override
    public Object visitSimpleNameExpr(CompileUnitParser.SimpleNameExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        String referName = ctx.SimpleName().getText();
        if (this.containVarName(referName)) {
            return this.visitTerminal(ctx.SimpleName());
        } else {
            String typeFullName = null;
            if (this.containImportName(referName)) {
                String fullUrl = this.getImportFullName(referName);
                typeFullName = TypeThreadCache.getByUrl(fullUrl).getTypeOptCode();
            } else {
                TypeThreadCache.getByUrl(referName);
                typeFullName = TypeThreadCache.getByUrl(referName).getTypeOptCode();
                this.addJavaTypeImport(typeFullName);
            }
            return TypeUtil.getTypeCode(typeFullName);
        }
    }

    @Override
    public Object visitAnonmousFuncExpr(CompileUnitParser.AnonmousFuncExprContext ctx) {
        return null;
    }

    @Override
    public Object visitMultiplyDivideExpr(CompileUnitParser.MultiplyDivideExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        sb.append(this.visitExpress(ctx.express(0)));
        sb.append(this.visitTerminal(ctx.Divide()));
        sb.append(this.visitTerminal(ctx.Multiply()));
        sb.append(this.visitExpress(ctx.express(1)));
        return sb.toString();
    }

    @Override
    public Object visitAndOrExpr(CompileUnitParser.AndOrExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        return String.valueOf(this.visitExpress(ctx.express(0))) +
                this.addLeftAndRightBlank(ctx.And()) +
                this.addLeftAndRightBlank(ctx.Or()) +
                this.visitExpress(ctx.express(1));
    }

    @Override
    public Object visitBooleanValExpr(CompileUnitParser.BooleanValExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        return String.valueOf(this.visitTerminal(ctx.False())) +
                this.visitTerminal(ctx.True());
    }

    @Override
    public Object visitPlusMinusExpr(CompileUnitParser.PlusMinusExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        return String.valueOf(this.visitExpress(ctx.express(0))) +
                this.visitTerminal(ctx.Plus()) +
                this.visitTerminal(ctx.Minus()) +
                this.visitExpress(ctx.express(1));
    }

    @Override
    public Object visitSimplifyMethodInvokeExpr(CompileUnitParser.SimplifyMethodInvokeExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        //校验方法是否存在
        List<TypeRefer> parameterTypes = ParameterVisitManager.getParameterTypes(this, ctx.parameters());
        TypeParser.getMethod(this.getThisType().buildTypeRefer(), ctx.SimpleName().getText(), parameterTypes);
        return this.visitTerminal(ctx.SimpleName()).toString() +
                this.visitTerminal(ctx.OpenParen()).toString() +
                this.visitParameters(ctx.parameters()).toString() +
                this.visitTerminal(ctx.CloseParen()).toString();
    }

    @Override
    public Object visitNullValExpr(CompileUnitParser.NullValExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        return this.visitTerminal(ctx.Null());
    }


    @Override
    public Object visitAssignValExpr(CompileUnitParser.AssignValExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        CompileUnitParser.ExpressContext leftExpr = ctx.express(0);
        CompileUnitParser.ExpressContext rightExpr = ctx.express(1);

        if (!(rightExpr instanceof CompileUnitParser.ObjectValueExprContext || rightExpr instanceof CompileUnitParser.ArrayValueExprContext)) {
            TypeRefer leftTypeRefer = ExpressAstParser.getOriginalType(leftExpr, this);
            TypeRefer rightTypeRefer = ExpressAstParser.getOriginalType(rightExpr, this);
            boolean needValidate = true;
            if (rightExpr instanceof CompileUnitParser.NumberValExprContext) {
                if (leftTypeRefer.isNumber()) {
                    needValidate = false;
                }
            }
            if (needValidate) {
                this.compareType(ctx, leftTypeRefer, rightTypeRefer);
            }
        }

        if (leftExpr instanceof CompileUnitParser.FieldAccessExprContext) {
            CompileUnitParser.FieldAccessExprContext fieldAccessExprContext = (CompileUnitParser.FieldAccessExprContext) leftExpr;
            VisitResult javaVisitResult = FieldAccessManager.visitSetter(
                    this,
                    fieldAccessExprContext.express(),
                    fieldAccessExprContext.SimpleName().getText(),
                    rightExpr);
            this.addJavaImports(javaVisitResult.getImports());
            return javaVisitResult.getScript();
        } else if (leftExpr instanceof CompileUnitParser.ArrayAccessExprContext) {
            CompileUnitParser.ArrayAccessExprContext arrayAccessExprContext = (CompileUnitParser.ArrayAccessExprContext) leftExpr;
            VisitResult javaVisitResult = ArrayAccessManager.visitSetter(this,
                    arrayAccessExprContext.express(0),
                    arrayAccessExprContext.express(1),
                    rightExpr);
            return javaVisitResult.getScript();
        } else {
            StringBuilder sb = new StringBuilder();
            sb.append(this.visitExpress(leftExpr));
            sb.append(" " + this.visitTerminal(ctx.Assign()) + " ");
            sb.append(this.visitExpress(rightExpr));
            return sb.toString();
        }
    }

    private void compareType(CompileUnitParser.AssignValExprContext ctx, TypeRefer requireType, TypeRefer providerType) {
        if (!TypeCompareMgr.singleEqualOrIsInstance(providerType, requireType)) {
            throw new ExpressBizException(ExpressResourceKey.ASSIGN_VALUE_TYPE_NOT_MATCH, null, true, ASTParser.getRuleContextDsl(this.dsl, ctx), requireType.getTypeId(), providerType.getTypeId());
        } else {
            if (requireType.getGenericTypes() != null) {
                if (providerType.getGenericTypes() == null) {
                    throw new ExpressBizException(ExpressResourceKey.ASSIGN_VALUE_GENERIC_COUNT_NOT_MATCH, null, true, ASTParser.getRuleContextDsl(this.dsl, ctx), requireType.getGenericTypes().size(), "0");
                } else {
                    if (requireType.getGenericTypes().size() != providerType.getGenericTypes().size()) {
                        throw new ExpressBizException(ExpressResourceKey.ASSIGN_VALUE_GENERIC_COUNT_NOT_MATCH, null, true, ASTParser.getRuleContextDsl(this.dsl, ctx), requireType.getGenericTypes().size(), providerType.getGenericTypes().size());
                    } else {
                        for (int i = 0; i < requireType.getGenericTypes().size(); i++) {
                            TypeRefer rGenericType = requireType.getGenericTypes().get(i);
                            TypeRefer pGenericType = providerType.getGenericTypes().get(i);
                            compareType(ctx, rGenericType, pGenericType);
                        }
                    }
                }
            } else {
                if (providerType.getGenericTypes() != null) {
                    throw new ExpressBizException(ExpressResourceKey.ASSIGN_VALUE_GENERIC_COUNT_NOT_MATCH, null, true, ASTParser.getRuleContextDsl(this.dsl, ctx), "0", providerType.getGenericTypes().size());
                }
            }
        }
    }


    @Override
    public Object visitCompareExpr(CompileUnitParser.CompareExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        CompileUnitParser.ExpressContext leftExpress = ctx.express(0);
        CompileUnitParser.ExpressContext rightExpress = ctx.express(1);
        CompileUnitParser.CompareOpContext compareOpContext = ctx.compareOp();
        //数字表达式
        if (compareOpContext.GreaterThan() != null || compareOpContext.GreaterThanEqual() != null
                || compareOpContext.LessThan() != null || compareOpContext.LessThanEqual() != null) {
            TypeRefer leftTypeRefer = ExpressAstParser.getOriginalType(leftExpress, this);
            TypeRefer rightTypeRefer = ExpressAstParser.getOriginalType(rightExpress, this);
            if (!leftTypeRefer.isNumber()) {
                String leftDsl = ASTParser.getRuleContextDsl(this.dsl, leftExpress);
                throw new ExpressException(String.format("%s is not number type", leftDsl));
            }
            if (!rightTypeRefer.isNumber()) {
                String rightDsl = ASTParser.getRuleContextDsl(this.dsl, rightExpress);
                throw new ExpressException(String.format("%s is not number type", rightDsl));
            }
        }

        if (compareOpContext.Equal() != null) {
            TypeRefer leftTypeRefer = ExpressAstParser.getOriginalType(leftExpress, this);
            if (leftTypeRefer.isString()) {
                return String.valueOf(this.visitExpress(ctx.express(0))) +
                        ".equals(" +
                        this.visitExpress(ctx.express(1)) + ")";
            }
        }

        return String.valueOf(this.visitExpress(ctx.express(0))) +
                this.visitCompareOp(ctx.compareOp()) +
                this.visitExpress(ctx.express(1));
    }


    @Override
    public Object visitStringValExpr(CompileUnitParser.StringValExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        return this.visitTerminal(ctx.StringLiteral());
    }

    @Override
    public Object visitPpmmPreExpr(CompileUnitParser.PpmmPreExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        return String.valueOf(this.visitTerminal(ctx.MinusMinus())) +
                this.visitTerminal(ctx.PlusPlus()) +
                this.visitExpress(ctx.express());
    }


    @Override
    public Object visitEnclosureExpr(CompileUnitParser.EnclosureExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        return String.valueOf(this.visitTerminal(ctx.OpenParen())) +
                this.visitExpress(ctx.express()) +
                this.visitTerminal(ctx.CloseParen());
    }

    @Override
    public Object visitJsonFieldAssignValue(CompileUnitParser.JsonFieldAssignValueContext ctx) {
        return null;
    }


    @Override
    public Object visitParameters(CompileUnitParser.ParametersContext ctx) {
        if (ctx == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        List<CompileUnitParser.ParameterContext> parameters = ctx.parameter();
        Method method = null;
        boolean isMethodInvoke = false;
        if (ctx.parent instanceof CompileUnitParser.MethodInvokeExprContext) {
            CompileUnitParser.MethodInvokeExprContext methodInvokeExprContext = (CompileUnitParser.MethodInvokeExprContext) ctx.parent;
            CompileUnitParser.ExpressContext expressContext = methodInvokeExprContext.express();
            TypeRefer typeRefer = ExpressAstParser.getOriginalType(expressContext, this);
            String methodName = methodInvokeExprContext.SimpleName().getText();
            List<TypeRefer> parameterTypes = ParameterVisitManager.getParameterTypes(this, methodInvokeExprContext.parameters());
            if (parameterTypes != null) {
                int index = 0;
                for (CompileUnitParser.ParameterContext parametersContext : methodInvokeExprContext.parameters().parameter()) {
                    parametersContext.express().requireType = parameterTypes.get(index);
                    index++;
                }
            }
            method = TypeParser.getMethod(typeRefer, methodName, parameterTypes);
            isMethodInvoke = true;
        }
        if (parameters != null && parameters.size() > 0) {
            int index = 0;
            for (CompileUnitParser.ParameterContext parameter : parameters) {
                if (index > 0) {
                    sb.append(",");
                }
                String parameterCode = null;
                if (isMethodInvoke) {
                    parameterCode = (String) ParameterVisitManager.visitParameter(this, method, parameter, index);
                } else {
                    parameterCode = this.visitParameter(parameter).toString();
                }
                sb.append(parameterCode);
                index++;
            }
        }
        return sb.toString();
    }

    @Override
    public Object visitParameter(CompileUnitParser.ParameterContext ctx) {
        if (ctx == null) {
            return "";
        }
        return this.visitExpress(ctx.express());
    }

    @Override
    public Object visitNotExpr(CompileUnitParser.NotExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        return String.valueOf(this.visitTerminal(ctx.Not())) +
                this.visitExpress(ctx.express());
    }

    @Override
    public Object visitVarDeclarationExpr(CompileUnitParser.VarDeclarationExprContext ctx) {
        if (ctx == null) {
            return "";
        }
        CompileUnitParser.TypeContext typeContext = ctx.type();
        CompileUnitParser.ExpressContext valueExpr = ctx.express();
        String varName = ctx.SimpleName().getText();

        TypeRefer typeRefer = null;
        ParserRuleContext parserRuleContext = this.getVarContext();
        if (typeContext != null) {
            typeRefer = TypeAstParser.getTypeRefer(typeContext, this);
        } else {
            if (valueExpr != null) {
                typeRefer = ExpressAstParser.getOriginalType(valueExpr, this);
            } else {
                typeRefer = new TypeRefer("any");
            }
        }
        String typeName = TypeVisitor.visit(typeRefer, this);
        if (typeRefer != null) {
            this.putContextVar(parserRuleContext, varName, typeRefer);
        }
        String finalStr = this.visitTerminal(ctx.Final()).toString();
        if (!StringUtils.isEmpty(finalStr)) {
            finalStr = finalStr + " ";
        }

        CompileUnitParser.ExpressContext valueExpress = ctx.express();
        String valueText = null;
        if (valueExpress == null) {
            Type type = TypeThreadCache.getType(typeRefer);
            NullValueVisitor nullValueVisitor = NullValueFactory.getSpi(type.getNullValueKind());
            valueText = nullValueVisitor.visit().getScript();
        } else {
            valueText = this.visitExpress(ctx.express()).toString();
        }
        String result = finalStr +
                typeName +
                " " +
                this.visitTerminal(ctx.SimpleName()) +
                " = "
                + valueText;
        return result;
    }

    @Override
    public Object visitCompareOp(CompileUnitParser.CompareOpContext ctx) {
        if (ctx == null) {
            return "";
        }
        return this.addLeftAndRightBlank(ctx.Equal()) +
                this.addLeftAndRightBlank(ctx.GreaterThan()) +
                this.addLeftAndRightBlank(ctx.GreaterThanEqual()) +
                this.addLeftAndRightBlank(ctx.IdentityEqual()) +
                this.addLeftAndRightBlank(ctx.LessThan()) +
                this.addLeftAndRightBlank(ctx.LessThanEqual()) +
                this.addLeftAndRightBlank(ctx.Modulo()) +
                this.addLeftAndRightBlank(ctx.NotEqual());
    }


    @Override
    public Object visitBlock(CompileUnitParser.BlockContext ctx) {
        if (ctx == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        this.appendWsAndStr(sb, "{");
        this.tabKeyCount++;
        //方法体
        List<CompileUnitParser.StatementContext> statementList = ctx.statement();
        if (statementList != null && statementList.size() > 0) {
            this.blockStack.push(ctx);
            this.varStack.push(ctx);
            this.varName_type_list.add(new VariableData(false));
            List<String> dslList = new ArrayList<>();
            this.context_statement_map.put(ctx, dslList);
            for (CompileUnitParser.StatementContext tmp : statementList) {
                dslList.add(this.visitStatement(tmp).toString());
            }
            for (String dsl : dslList) {
                sb.append(dsl);
            }
            this.removeContextVar();
            this.context_statement_map.remove(ctx);
            this.varStack.pop();
            this.blockStack.pop();
        }
        this.tabKeyCount--;
        this.appendWsAndStr(sb, "\n");
        this.appendTabKey(sb);
        sb.append("}");
        return sb.toString();
    }

    @Override
    public Object visitExprStatement(CompileUnitParser.ExprStatementContext ctx) {
        if (ctx == null) {
            return "";
        }
        return this.visitExpress(ctx.express());
    }

    @Override
    public Object visitSuperStatement(CompileUnitParser.SuperStatementContext ctx) {
        if (ctx == null) {
            return "";
        }
        return String.valueOf(this.visitTerminal(ctx.Super())) +
                this.visitTerminal(ctx.OpenParen()) +
                this.visitParameters(ctx.parameters()) +
                this.visitTerminal(ctx.CloseParen());
    }

    @Override
    public Object visitEmptyStatement(CompileUnitParser.EmptyStatementContext ctx) {
        return "";
    }


    @Override
    public Object visitForStatement(CompileUnitParser.ForStatementContext ctx) {
        if (ctx == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        sb.append(this.visitTerminal(ctx.For()));
        sb.append(this.visitTerminal(ctx.OpenParen()));
        List<CompileUnitParser.ExpressContext> expresses = ctx.express();
        List<TerminalNode> semiColon = ctx.SemiColon();
        for (int i = 0; i < expresses.size(); i++) {
            sb.append(this.visitExpress(expresses.get(i)));
            if (i > 0) {
                sb.append(this.visitTerminal(semiColon.get(i - 1)));
            }
        }
        sb.append(this.visitTerminal(ctx.CloseParen()));
        sb.append(this.visitBlock(ctx.block()));
        return sb.toString();
    }

    @Override
    public Object visitWhileStatement(CompileUnitParser.WhileStatementContext ctx) {
        if (ctx == null) {
            return "";
        }
        return String.valueOf(this.visitTerminal(ctx.While())) +
                this.visitTerminal(ctx.OpenParen()) +
                this.visitExpress(ctx.express()) +
                this.visitTerminal(ctx.CloseParen()) +
                this.visitBlock(ctx.block());
    }

    @Override
    public Object visitForEachStatement(CompileUnitParser.ForEachStatementContext ctx) {
        if (ctx == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        sb.append("\n");
        TypeRefer typeRefer = ExpressAstParser.getOriginalType(ctx.express(), this);
        String varName = ctx.SimpleName().getText();
        String expressDSL = ExpressVisitManager.visit(this, ctx.express()).toString();
        TypeRefer itemTypeRefer = typeRefer.getGenericType(0);
        sb.append(String.format("for(%s %s : %s )", TypeVisitor.visit(itemTypeRefer, this), varName, expressDSL));
        //初始化变量栈
        this.varStack.push(ctx);
        this.varName_type_list.add(new VariableData(true));
        this.putContextVar(this.getVarContext(), varName, itemTypeRefer);
        sb.append(this.visitBlock(ctx.block()).toString());
        this.removeContextVar();
        this.varStack.pop();
        return sb.toString();
    }

    @Override
    public Object visitBreakStatement(CompileUnitParser.BreakStatementContext ctx) {
        if (ctx == null) {
            return "";
        }
        return this.visitTerminal(ctx.Break());
    }

    @Override
    public Object visitContinueStatement(CompileUnitParser.ContinueStatementContext ctx) {
        if (ctx == null) {
            return "";
        }
        return this.visitTerminal(ctx.Continue());
    }

    @Override
    public Object visitSwitchStatement(CompileUnitParser.SwitchStatementContext ctx) {
        return "";
    }

    @Override
    public Object visitSelectStatement(CompileUnitParser.SelectStatementContext ctx) {
        if (ctx == null) {
            return "";
        }
        return this.visitIfStatement(ctx.ifStatement());
    }

    @Override
    public Object visitSwitchBlock(CompileUnitParser.SwitchBlockContext ctx) {
        return "";
    }

    @Override
    public Object visitSwitchCase(CompileUnitParser.SwitchCaseContext ctx) {
        return "";
    }

    @Override
    public Object visitReturnStatement(CompileUnitParser.ReturnStatementContext ctx) {
        if (ctx == null) {
            return "";
        }
        return this.visitTerminal(ctx.Return()) +
                " " +
                this.visitExpress(ctx.express());
    }

    @Override
    public Object visitThrowStatement(CompileUnitParser.ThrowStatementContext ctx) {
        if (ctx == null) {
            return "";
        }
        return String.valueOf(this.visitTerminal(ctx.Throw())) +
                this.visitExpress(ctx.express());
    }

    @Override
    public Object visitTryCatchFinallyStatement(CompileUnitParser.TryCatchFinallyStatementContext ctx) {
        if (ctx == null) {
            return "";
        }
        return String.valueOf(this.visitTryBlock(ctx.tryBlock())) +
                this.visitCatchBlock(ctx.catchBlock()) +
                this.visitFinallyBlock(ctx.finallyBlock());
    }

    @Override
    public Object visitIfStatement(CompileUnitParser.IfStatementContext ctx) {
        if (ctx == null) {
            return "";
        }
        List<CompileUnitParser.BlockContext> blocks = ctx.block();
        StringBuilder sb = new StringBuilder();
        sb.append(this.addRightBlank(ctx.If()));
        sb.append(this.visitTerminal(ctx.OpenParen()));
        sb.append(this.visitExpress(ctx.express()));
        sb.append(this.visitTerminal(ctx.CloseParen()));
        sb.append(this.visitBlock(blocks.get(0)));
        sb.append(this.addLeftAndRightBlank(ctx.Else()));
        if (blocks.size() > 1) {
            sb.append(this.visitBlock(blocks.get(1)));
        }
        sb.append(this.visitIfStatement(ctx.ifStatement()));
        return sb.toString();
    }

    @Override
    public Object visitTryBlock(CompileUnitParser.TryBlockContext ctx) {
        if (ctx == null) {
            return "";
        }
        return String.valueOf(this.visitTerminal(ctx.Try())) +
                this.visitBlock(ctx.block());
    }

    @Override
    public Object visitCatchBlock(CompileUnitParser.CatchBlockContext ctx) {
        if (ctx == null) {
            return "";
        }
        return String.valueOf(this.visitTerminal(ctx.Catch())) +
                this.visitTerminal(ctx.OpenParen()) +
                this.visitParameterDeclaration(ctx.parameterDeclaration()) +
                this.visitTerminal(ctx.CloseParen()) +
                this.visitBlock(ctx.block());
    }

    @Override
    public Object visitFinallyBlock(CompileUnitParser.FinallyBlockContext ctx) {
        if (ctx == null) {
            return "";
        }
        return String.valueOf(this.visitTerminal(ctx.Finally())) +
                this.visitBlock(ctx.block());
    }

    @Override
    public Object visitFunctionDeclaration(CompileUnitParser.FunctionDeclarationContext ctx) {
        return "";
    }

    @Override
    public Object visit(ParseTree tree) {
        return "";
    }

    @Override
    public Object visitChildren(RuleNode node) {
        return "";
    }

    @Override
    public Object visitTerminal(TerminalNode node) {
        if (node == null) {
            return "";
        }
        return node.getText();
    }

    @Override
    public Object visitErrorNode(ErrorNode node) {
        return "";
    }

    public Object visitExpress(CompileUnitParser.ExpressContext ctx) {
        if (ctx == null) {
            return "null";
        }
        //先初始化类型
        ExpressAstParser.initType(ctx, this);
        return ExpressVisitManager.getVisitor(ctx).visit(ctx, this);
    }

    public Object visitStatement(CompileUnitParser.StatementContext ctx) {
        if (ctx == null) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        sb.append("\n");
        this.appendTabKey(sb);
        sb.append(StatementVisitor.visit(ctx, this));
        return sb.toString();
    }

    @Override
    public Type getThisType() {
        return this.thisDSLClass;
    }

    @Override
    public Type getType(TypeRefer typeRefer) {
        return TypeThreadCache.getType(typeRefer);
    }

    @Override
    public Type getType(String url) {
        return TypeThreadCache.getByUrl(url);
    }

    @Override
    public void addImport(String fullName) {

    }

    @Override
    public void addImports(Collection<String> imports) {

    }

    @Override
    public boolean containImportName(String typeName) {
        return this.dslImportMap.containsKey(typeName);
    }

    @Override
    public String getImportFullName(String typeName) {
        return this.dslImportMap.get(typeName);
    }


    @Override
    public TypeRefer getVarType(String varName) {
        List<VariableData> variableNameList = this.getVarName_type_list();
        for (int i = variableNameList.size() - 1; i >= 0; i--) {
            VariableData data = variableNameList.get(i);
            if (data.contains(varName)) {
                return data.get(varName);
            }
        }
        throw new ExpressException(String.format("variable %s is undefined .", varName));
    }

    @Override
    public boolean containVarName(String varName) {
        List<VariableData> variableNameList = this.getVarName_type_list();
        for (int i = variableNameList.size() - 1; i >= 0; i--) {
            if (variableNameList.get(i).contains(varName)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void removeVariable(String varName) {
        this.removeContextVar();
    }


    @Override
    public void addVariable(String varName, TypeRefer typeRefer) {
        List<VariableData> variableNameList = this.getVarName_type_list();
        if (variableNameList.size() == 0) {
            throw new ExpressException(String.format("The context has not been initialized yet, so variables %s can not be added", varName));
        }
        boolean containVar = false;
        for (int i = variableNameList.size() - 1; i >= 0; i--) {
            VariableData variableData = variableNameList.get(i);
            if (variableData.contains(varName)) {
                containVar = true;
                break;
            } else {
                if (variableData.isolate) {
                    containVar = false;
                    break;
                } else {
                    continue;
                }
            }
        }
        if (containVar) {
            throw new ExpressException(String.format("variable %s already exists.", varName));
        } else {
            int lastIndex = this.varName_type_list.size();
            VariableData lastData = this.varName_type_list.get(lastIndex - 1);
            lastData.addVar(varName, typeRefer);
        }
    }

    private String addLeftAndRightBlank(TerminalNode terminalNode) {
        if (terminalNode == null) {
            return "";
        } else {
            return " " + this.visitTerminal(terminalNode) + " ";
        }
    }

    private String addRightBlank(TerminalNode terminalNode) {
        if (terminalNode == null) {
            return "";
        } else {
            return this.visitTerminal(terminalNode) + " ";
        }
    }

}